﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;

using Cinch;
using MEFedMVVM.ViewModelLocator;
using MEFedMVVM.Services.Contracts;
using MEFedMVVM.Common;


namespace Anata.Client
{
    /// <summary>
    /// </summary>
    [ExportViewModel("KaryawanViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class KaryawanViewModel : EditableValidatingViewModelBase
    {
        #region Data
        
        private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private DataWrapper<Int32> idKaryawan;
        private DataWrapper<String> nama;
        private DataWrapper<String> alamat;
        private DataWrapper<String> noTelepon;
        private DataWrapper<String> noKTP;
        private DataWrapper<String> jenisKelamin;
        private DataWrapper<DateTime?> tanggalLahir;
        private DataWrapper<String> status;
        private DataWrapper<String> agama;
        private DataWrapper<String> golDarah;
        private DataWrapper<DateTime?> tanggalMasuk;
        private DataWrapper<DateTime?> tanggalKeluar;
        private DataWrapper<Int32?> idCabang;

        private bool isBusy = false;
        private bool isCollectionsChanged = false;
        private KaryawanThumbnailViewModel loadedKaryawanThumbnail;
        #endregion

        private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;

        #region Data.Rules
        private static SimpleRule namaRule;
        #endregion

        #region Data.VMs
        private KaryawanKehadiranViewModel kehadiranTerakhir;
        private DispatcherNotifiedObservableCollection<KaryawanLayananViewModel> karyawanLayanans;
        private ICollectionView karyawanLayanansCV;
        private DispatcherNotifiedObservableCollection<TransaksiLayananViewModel> jadwalKaryawans;
        private ICollectionView jadwalKaryawansCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IKaryawanProvider karyawanProvider;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public KaryawanViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IViewAwareStatus viewAwareStatusService,
            IKaryawanProvider karyawanProvider,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.viewAwareStatusService = viewAwareStatusService;
            this.karyawanProvider = karyawanProvider;
            this.referenceProvider = referenceProvider;
            this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            #endregion

            #region Constructor.SetupCommands
            KaryawanLayananAddCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanLayananAddCommand, ExecuteKaryawanLayananAddCommand);
            KaryawanLayananDeleteCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanLayananDeleteCommand, ExecuteKaryawanLayananDeleteCommand);
            KaryawanSaveCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanSaveCommand, ExecuteKaryawanSaveCommand);
            KehadiranTerakhirSaveCommand = new SimpleCommand<Object, Object>(CanExecuteKehadiranTerakhirSaveCommand, ExecuteKehadiranTerakhirSaveCommand);
            JadwalKaryawanSaveCommand = new SimpleCommand<Object, Object>(CanExecuteJadwalKaryawanSaveCommand, ExecuteJadwalKaryawanSaveCommand);
            KaryawanExitCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanExitCommand, ExecuteKaryawanExitCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            IdKaryawan = new DataWrapper<Int32>(this, idKaryawanChangeArgs);
            IdKaryawan.IsEditable = true;
            Nama = new DataWrapper<String>(this, namaChangeArgs);
            Nama.IsEditable = true;
            Alamat = new DataWrapper<String>(this, alamatChangeArgs);
            Alamat.IsEditable = true;
            NoTelepon = new DataWrapper<String>(this, noTeleponChangeArgs);
            NoTelepon.IsEditable = true;
            NoKTP = new DataWrapper<String>(this, noKTPChangeArgs);
            NoKTP.IsEditable = true;
            JenisKelamin = new DataWrapper<String>(this, jenisKelaminChangeArgs);
            JenisKelamin.IsEditable = true;
            TanggalLahir = new DataWrapper<DateTime?>(this, tanggalLahirChangeArgs);
            TanggalLahir.IsEditable = true;
            Status = new DataWrapper<String>(this, statusChangeArgs);
            Status.IsEditable = true;
            Agama = new DataWrapper<String>(this, agamaChangeArgs);
            Agama.IsEditable = true;
            GolDarah = new DataWrapper<String>(this, golDarahChangeArgs);
            GolDarah.IsEditable = true;
            TanggalMasuk = new DataWrapper<DateTime?>(this, tanggalMasukChangeArgs);
            TanggalMasuk.IsEditable = true;
            TanggalKeluar = new DataWrapper<DateTime?>(this, tanggalKeluarChangeArgs);
            TanggalKeluar.IsEditable = true;
            IdCabang = new DataWrapper<Int32?>(this, idCabangChangeArgs);
            IdCabang.IsEditable = true;
            #endregion

            //fetch list of all DataWrappers, so they can be used again later without the
            //need for reflection
            cachedListOfDataWrappers =
                DataWrapperHelper.GetWrapperProperties<KaryawanViewModel>(this);

            #region Constructor.SetupValidationRules
            //nama.AddRule(namaRule);
            #endregion

            #region Constructor.SetupVMs
            KehadiranTerakhir = new KaryawanKehadiranViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            KaryawanLayanans = new DispatcherNotifiedObservableCollection<KaryawanLayananViewModel>();
            KaryawanLayanansCV = CollectionViewSource.GetDefaultView(karyawanLayanans);
            JadwalKaryawans = new DispatcherNotifiedObservableCollection<TransaksiLayananViewModel>();
            JadwalKaryawansCV = CollectionViewSource.GetDefaultView(jadwalKaryawans);
            #endregion

            Mediator.Instance.Register(this);
        }
        #endregion

        #region Statics
        static KaryawanViewModel()
        {
            namaRule = new SimpleRule("DataValue", "Nama tidak valid",
                (Object domainObject) =>
                {
                    DataWrapper<String> obj = (DataWrapper<String>)domainObject;
                    return obj.DataValue == "";
                });
        }
        #endregion

        #region PublicProperties
        #region Public.Commands
        /*
        //public SimpleCommand<Object, Object> KonsumenSelectCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiLayananAddCommand { get; private set; }
        //public SimpleCommand<Object, Object> HapusTransaksiLayananCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiProdukAddCommand { get; private set; }
        //public SimpleCommand<Object, Object> HapusTransaksiProdukCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiPembayaranAddCommand { get; private set; }
        //public SimpleCommand<Object, Object> HapusTransaksiPembayaranCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiPayCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiPayCancelCommand { get; private set; }
        //public SimpleCommand<Object, Object> TransaksiPayFinishCommand { get; private set; }
        */
        public SimpleCommand<Object, Object> KaryawanLayananAddCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanLayananDeleteCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanSaveCommand { get; private set; }
        public SimpleCommand<Object, Object> KehadiranTerakhirSaveCommand { get; private set; }
        public SimpleCommand<Object, Object> JadwalKaryawanSaveCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanExitCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        /// <summary>
        /// The current ViewMode, when changed will loop
        /// through all nested DataWrapper objects and change
        /// their state also
        /// </summary>

        static PropertyChangedEventArgs currentViewModeChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.CurrentViewMode);

        public ViewMode CurrentViewMode
        {
            get { return currentViewMode; }
            set
            {
                currentViewMode = value;

                switch (currentViewMode)
                {
                    case ViewMode.AddMode:
                        this.DisplayName = "Transaksi Baru";
                        break;
                    case ViewMode.EditMode:
                        this.DisplayName = "Ubah Transaksi";
                        break;
                    case ViewMode.ViewOnlyMode:
                        this.DisplayName = "Lihat Transaksi";
                        break;
                }

                //Now change all the CachedListOfDataWrappers
                //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                //state based on the new ViewMode applied to the ViewModel
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetMode(
                    CachedListOfDataWrappers,
                    currentViewMode);

                NotifyPropertyChanged(currentViewModeChangeArgs);
            }
        }
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idKaryawanChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.IdKaryawan);
        public DataWrapper<Int32> IdKaryawan
        {
            get { return idKaryawan; }
            set
            {
                idKaryawan = value;
                NotifyPropertyChanged(idKaryawanChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.Nama);
        public DataWrapper<String> Nama
        {
            get { return nama; }
            set
            {
                nama = value;
                NotifyPropertyChanged(namaChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs alamatChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.Alamat);
        public DataWrapper<String> Alamat
        {
            get { return alamat; }
            set
            {
                alamat = value;
                NotifyPropertyChanged(alamatChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs noTeleponChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.NoTelepon);
        public DataWrapper<String> NoTelepon
        {
            get { return noTelepon; }
            set
            {
                noTelepon = value;
                NotifyPropertyChanged(noTeleponChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs noKTPChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.NoKTP);
        public DataWrapper<String> NoKTP
        {
            get { return noKTP; }
            set
            {
                noKTP = value;
                NotifyPropertyChanged(noKTPChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs jenisKelaminChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.JenisKelamin);
        public DataWrapper<String> JenisKelamin
        {
            get { return jenisKelamin; }
            set
            {
                jenisKelamin = value;
                NotifyPropertyChanged(jenisKelaminChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs tanggalLahirChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.TanggalLahir);
        public DataWrapper<DateTime?> TanggalLahir
        {
            get { return tanggalLahir; }
            set
            {
                tanggalLahir = value;
                NotifyPropertyChanged(tanggalLahirChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs statusChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.Status);
        public DataWrapper<String> Status
        {
            get { return status; }
            set
            {
                status = value;
                NotifyPropertyChanged(statusChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs agamaChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.Agama);
        public DataWrapper<String> Agama
        {
            get { return agama; }
            set
            {
                agama = value;
                NotifyPropertyChanged(agamaChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs golDarahChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.GolDarah);
        public DataWrapper<String> GolDarah
        {
            get { return golDarah; }
            set
            {
                golDarah = value;
                NotifyPropertyChanged(golDarahChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs tanggalMasukChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.TanggalMasuk);
        public DataWrapper<DateTime?> TanggalMasuk
        {
            get { return tanggalMasuk; }
            set
            {
                tanggalMasuk = value;
                NotifyPropertyChanged(tanggalMasukChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs tanggalKeluarChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.TanggalKeluar);
        public DataWrapper<DateTime?> TanggalKeluar
        {
            get { return tanggalKeluar; }
            set
            {
                tanggalKeluar = value;
                NotifyPropertyChanged(tanggalKeluarChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idCabangChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.IdCabang);
        public DataWrapper<Int32?> IdCabang
        {
            get { return idCabang; }
            set
            {
                idCabang = value;
                NotifyPropertyChanged(idCabangChangeArgs);
            }
        }
        #endregion

        #region Public.Busy
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBusyChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.IsBusy);
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                foreach (var item in karyawanLayanans)
                {
                    item.IsBusy = value;
                }
                foreach (var item in jadwalKaryawans)
                {
                    item.IsBusy = value;
                }
                NotifyPropertyChanged(isBusyChangeArgs);
            }
        }
        #endregion

        #region Public.Cached Collection
        /// <summary>
        /// Returns cached collection of DataWrapperBase
        /// </summary>
        public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
        {
            get { return cachedListOfDataWrappers; }
        }
        #endregion

        #region Public.DataVM
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs kehadiranTerakhirChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.KehadiranTerakhir);
        public KaryawanKehadiranViewModel KehadiranTerakhir
        {
            get { return kehadiranTerakhir; }
            set
            {
                kehadiranTerakhir = value;
                NotifyPropertyChanged(kehadiranTerakhirChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs karyawanLayanansChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.KaryawanLayanans);
        public DispatcherNotifiedObservableCollection<KaryawanLayananViewModel> KaryawanLayanans
        {
            get { return karyawanLayanans; }
            set
            {
                karyawanLayanans = value;
                NotifyPropertyChanged(karyawanLayanansChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs karyawanLayanansCVChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.KaryawanLayanansCV);
        public ICollectionView KaryawanLayanansCV
        {
            get { return karyawanLayanansCV; }
            set
            {
                karyawanLayanansCV = value;
                NotifyPropertyChanged(karyawanLayanansCVChangeArgs);
            }
        }
        
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs jadwalKaryawansChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.JadwalKaryawans);
        public DispatcherNotifiedObservableCollection<TransaksiLayananViewModel> JadwalKaryawans
        {
            get { return jadwalKaryawans; }
            set
            {
                jadwalKaryawans = value;
                NotifyPropertyChanged(jadwalKaryawansChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs jadwalKaryawansCVChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.JadwalKaryawansCV);
        public ICollectionView JadwalKaryawansCV
        {
            get { return jadwalKaryawansCV; }
            set
            {
                jadwalKaryawansCV = value;
                NotifyPropertyChanged(jadwalKaryawansCVChangeArgs);
            }
        }
        #endregion

        #region Public.SummaryData
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs statusKaryawanChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.StatusKaryawan);
        public int StatusKaryawan
        {
            get
            {
                int retval = 0;
                if (tanggalKeluar.DataValue.HasValue)
                {
                    retval = 99;
                }
                else if (kehadiranTerakhir.WaktuMasuk.DataValue.HasValue)
                {
                    retval = 0;
                }
                else
                {
                    retval = 1;
                }
                return retval;
            }
        }
        #endregion
        #endregion

        #region PublicMethods
        public void WorkspaceSave()
        {
            IsBusy = true;
            karyawanProvider.LazySaveKaryawan(this, PostSaveKaryawan);
        }
        public void WorkspaceSaveKehadiranTerakhir()
        {
            IsBusy = true;
            karyawanProvider.LazySaveKehadiranTerakhir(this, PostSaveKaryawan);
        }
        public void WorkspaceSaveJadwal()
        {
            IsBusy = true;
            karyawanProvider.LazySaveJadwalKaryawan(this, PostSaveKaryawan);
        }
        public void WorkspaceSaveAndExit()
        {
            IsBusy = true;
            karyawanProvider.LazySaveJadwalKaryawan(this, PostSaveAndExitJadwalKaryawan);
        }
        public void WorkspaceExit()
        {
            Mediator.Instance.NotifyColleagues<KaryawanThumbnailViewModel>(
                "DeactivateKaryawanDetail", loadedKaryawanThumbnail);
            this.loadedKaryawanThumbnail = null;
        }
        #region PublicMethods.ChildCreator
        public KaryawanKehadiranViewModel ForceCreateChildKaryawanKehadiranVM()
        {
            return new KaryawanKehadiranViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public KaryawanLayananViewModel ForceCreateChildKaryawanLayananVM()
        {
            return new KaryawanLayananViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        public TransaksiLayananViewModel ForceCreateChildTransaksiLayananVM()
        {
            return new TransaksiLayananViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
        }
        #endregion
        #endregion

        #region CommandHandlers
        #region CommandHandlers.Editors
        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanLayananAddCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanLayananAddCommand(Object args)
        {
            KaryawanLayananViewModel klvm = new KaryawanLayananViewModel(
                messageBoxService,
                uiVisualizerService,
                referenceProvider);
            klvm.BeginEdit();
            karyawanLayanans.Add(klvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanLayananDeleteCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanLayananDeleteCommand(Object args)
        {
            KaryawanLayananViewModel klvm = args as KaryawanLayananViewModel;
            if (karyawanLayanansCV.Contains(klvm))
            {
                karyawanLayanans.Remove(klvm);
                isCollectionsChanged = true;
            }
        }
        #endregion

        #region CommandHandlers.Finalizers
        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanSaveCommand(Object args)
        {
            return !IsBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanSaveCommand(Object args)
        {
            if (IsDirty) 
            {
                if (IsValid)
                {
                    //TODO, save to database;
                    WorkspaceSave();
                }
                else
                {
                    //TODO:
                    messageBoxService.ShowError("gagal save, not valid");
                }
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKehadiranTerakhirSaveCommand(Object args)
        {
            return !IsBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKehadiranTerakhirSaveCommand(Object args)
        {
            if (IsDirty)
            {
                if (IsValid)
                {
                    //TODO, save to database;
                    WorkspaceSaveKehadiranTerakhir();
                }
                else
                {
                    //TODO:
                    messageBoxService.ShowError("gagal save, not valid");
                }
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteJadwalKaryawanSaveCommand(Object args)
        {
            return !IsBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteJadwalKaryawanSaveCommand(Object args)
        {
            if (IsDirty)
            {
                if (IsValid)
                {
                    //TODO, save to database;
                    WorkspaceSaveJadwal();
                }
                else
                {
                    //TODO:
                    messageBoxService.ShowError("gagal save, not valid");
                }
            }
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanExitCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanExitCommand(Object args)
        {
            if (IsDirty && !IsBusy)
            {
                CustomDialogResults result =
                    messageBoxService.ShowYesNoCancel("Simpan perubahan?",
                        CustomDialogIcons.Question);
                if (result == CustomDialogResults.Yes)
                {
                    if (IsValid)
                    {
                        WorkspaceSaveAndExit();
                    }
                    else
                    {
                        //TODO:
                        messageBoxService.ShowError("gagal save, not valid");
                    }
                }
                else if (result == CustomDialogResults.No)
                {
                    //CancelEdit();
                    WorkspaceExit();
                }
                else if (result == CustomDialogResults.Cancel)
                {
                    //do nothing
                }
                else
                {
                    Console.WriteLine("wah2 gawat");
                }
            }
            else
            {
                WorkspaceExit();
            }
        }
        #endregion
        #endregion

        #region MediatorMessageSinks
        [MediatorMessageSink("LoadKaryawanThumbnailToWorkspace")]
        private void LoadKaryawanThumbnailToWorkspace(KaryawanThumbnailViewModel ktvm)
        {
            LoadKaryawanThumbnailInternal(ktvm);
        }
        [MediatorMessageSink("TryCloseKaryawanWorkspace")]
        private void TryCloseKaryawanWorkspace(KaryawanThumbnailViewModel ktvm)
        {
            if (ktvm.Equals(loadedKaryawanThumbnail))
            {
                KaryawanExitCommand.Execute(null);
            }
        }
        [MediatorMessageSink("TryRemoveKaryawanLayanan")]
        private void TryRemoveKaryawanLayanan(KaryawanLayananViewModel klvm)
        {
            KaryawanLayananDeleteCommand.Execute(klvm);
        }
        #endregion

        #region PrivateMethods
        #region PrivateMethods.OnViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            var view = viewAwareStatusService.View;
            IWorkSpaceAware workspaceData = (IWorkSpaceAware)view;
            LoadKaryawanThumbnailInternal((KaryawanThumbnailViewModel)workspaceData.WorkSpaceContextualData.DataValue);
        }
        #endregion

        #region PrivateMethods.Testers
        private bool IsCollectionsValid
        {
            get
            {
                Boolean collectionValid = true;

                foreach (KaryawanLayananViewModel karyawanLayanan in karyawanLayanans)
                {
                    try
                    {
                        collectionValid &= karyawanLayanan.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                foreach (TransaksiLayananViewModel jadwalKaryawan in jadwalKaryawans)
                {
                    try
                    {
                        collectionValid &= jadwalKaryawan.IsValid;
                        if (!collectionValid)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionValid = false;
                    }
                }

                return collectionValid;
            }
        }
        private bool IsCollectionsDirty
        {
            get
            {
                Boolean collectionsDirty = false;

                foreach (KaryawanLayananViewModel karyawanLayanan in karyawanLayanans)
                {
                    try
                    {
                        collectionsDirty |= karyawanLayanan.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                foreach (TransaksiLayananViewModel jadwalKaryawan in jadwalKaryawans)
                {
                    try
                    {
                        collectionsDirty |= jadwalKaryawan.IsDirty;
                        if (collectionsDirty)
                            break;
                    }
                    catch (Exception)
                    {
                        collectionsDirty = true;
                    }
                }

                return collectionsDirty;
            }
        }
        #endregion

        #region PrivateMethods.Loader
        private void LoadKaryawanThumbnailInternal(KaryawanThumbnailViewModel ktvm)
        {
            loadedKaryawanThumbnail = ktvm;
            IdKaryawan.DataValue = ktvm.IdKaryawan;
            if (loadedKaryawanThumbnail.IdKaryawan == 0)
            {
                //karyawan baru
                //SynchFromThumbnail(ktvm);
                BeginEdit();
            }
            else
            {
                //karyawan lama
                IsBusy = true;
                karyawanProvider.LazyLoadJadwalKaryawan(this, PostLoadJadwalKaryawan);
            }
        }
        #endregion

        #region PrivateMethods.PostSaver
        private void PostSaveKaryawan(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
                //do nothing, window dah closed
            }
            else if (kvm != null)
            {
                //tidak ada masalah dalam saving
                EndEdit();
                SynchToThumbnail(loadedKaryawanThumbnail);
                List<int> updatedIDs = new List<int>();
                foreach (var jadwal in jadwalKaryawans)
                {
                    if (!updatedIDs.Contains(jadwal.IdTransaksi.DataValue.Value))
                    {
                        Mediator.Instance.NotifyColleagues<int>("TryRefreshTransaksiThumbnail", jadwal.IdTransaksi.DataValue.Value);
                        updatedIDs.Add(jadwal.IdTransaksi.DataValue.Value);
                    }
                }
                BeginEdit();
                IsBusy = false;
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        private void PostSaveAndExitKaryawan(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                //tidak ada masalah dalam saving
                EndEdit();
                SynchToThumbnail(loadedKaryawanThumbnail);
                List<int> updatedIDs = new List<int>();
                foreach (var jadwal in jadwalKaryawans)
                {
                    if (!updatedIDs.Contains(jadwal.IdTransaksi.DataValue.Value))
                    {
                        Mediator.Instance.NotifyColleagues<int>("TryRefreshTransaksiThumbnail", jadwal.IdTransaksi.DataValue.Value);
                        updatedIDs.Add(jadwal.IdTransaksi.DataValue.Value);
                    }
                }
                IsBusy = false;
                WorkspaceExit();
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
            }
        }
        private void PostSaveAndExitKehadiranTerakhir(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                //tidak ada masalah dalam saving
                //SynchToThumbnail(loadedKaryawanThumbnail);
                //IsBusy = false;
                //WorkspaceExit();
                karyawanProvider.LazySaveKaryawan(this, PostSaveAndExitKaryawan);
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
            }
        }
        private void PostSaveAndExitJadwalKaryawan(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                //tidak ada masalah dalam saving
                //SynchToThumbnail(loadedKaryawanThumbnail);
                //IsBusy = false;
                //WorkspaceExit();
                karyawanProvider.LazySaveKehadiranTerakhir(this, PostSaveAndExitKehadiranTerakhir);
            }
            else
            {
                messageBoxService.ShowError("gagal saving, coba lagi");
                IsBusy = false;
            }
        }
        #endregion

        #region PrivateMethods.PostLoader
        private void PostLoadKaryawan(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                SynchToThumbnail(loadedKaryawanThumbnail);
                IsBusy = false;
                BeginEdit();
            }
            else
            {
                messageBoxService.ShowError("gagal loading, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        private void PostLoadKehadiranTerakhir(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                //SynchToThumbnail(loadedKaryawanThumbnail);
                //IsBusy = false;
                //BeginEdit();
                karyawanProvider.LazyLoadKaryawan(this, PostLoadKaryawan);
            }
            else
            {
                messageBoxService.ShowError("gagal loading, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        private void PostLoadJadwalKaryawan(KaryawanViewModel kvm)
        {
            if (loadedKaryawanThumbnail == null)
            {
            }
            else if (kvm != null)
            {
                //SynchToThumbnail(loadedKaryawanThumbnail);
                //IsBusy = false;
                //BeginEdit();
                karyawanProvider.LazyLoadKehadiranTerakhir(this, PostLoadKehadiranTerakhir);
            }
            else
            {
                messageBoxService.ShowError("gagal loading, coba lagi");
                IsBusy = false;
                BeginEdit();
            }
        }
        #endregion

        #region PrivateMethods.Synchronizer
        /*
        private void SynchFromThumbnail(TransaksiThumbnailViewModel ttvm)
        {
            IdTransaksi.DataValue = ttvm.IdTransaksi;
            IdKonsumen.DataValue = ttvm.IdKonsumen;
            NamaKonsumen = ttvm.NamaKonsumen;
            AlamatKonsumen = ttvm.AlamatKonsumen;
            TeleponKonsumen = ttvm.TeleponKonsumen;
            IdCabang.DataValue = ttvm.IdCabang;
            WaktuBuat.DataValue = ttvm.WaktuBuat;
            WaktuSelesai.DataValue = ttvm.WaktuSelesai;
            KoreksiHarga.DataValue = ttvm.KoreksiHarga;

            TransaksiLayanans.Clear();
            TransaksiLayananViewModel tlvm = null;
            foreach (TransaksiLayananThumbnailViewModel tltvm in ttvm.TransaksiLayanans)
            {
                tlvm = new TransaksiLayananViewModel(
                    messageBoxService,
                    uiVisualizerService,
                    referenceProvider);
                tlvm.IdTransaksiLayanan.DataValue = tltvm.IdTransaksiLayanan;
                tlvm.IdTransaksi.DataValue = tltvm.IdTransaksi;
                tlvm.IdLayanan.DataValue = tltvm.IdLayanan;
                tlvm.NamaLayanan = tltvm.NamaLayanan;
                tlvm.HargaLayanan = tltvm.HargaLayanan;
                tlvm.IdKaryawan.DataValue = tltvm.IdKaryawan;
                tlvm.NamaKaryawan = tltvm.NamaKaryawan;
                tlvm.KomisiKaryawan = tltvm.KomisiKaryawan;
                tlvm.NamaPromo.DataValue = tltvm.NamaPromo;
                tlvm.PotonganPromo.DataValue = tltvm.PotonganPromo;
                tlvm.NilaiKepuasan.DataValue = tltvm.NilaiKepuasan;
                tlvm.NamaFreeGift.DataValue = tltvm.NamaFreeGift;
                tlvm.IdJenisStok.DataValue = tltvm.IdJenisStok;
                tlvm.NamaJenisStok = tltvm.NamaJenisStok;
                tlvm.JumlahFreeGift.DataValue = tltvm.JumlahFreeGift;
                tlvm.WaktuBuat.DataValue = tltvm.WaktuBuat;
                tlvm.WaktuTunggu.DataValue = tltvm.WaktuTunggu;
                tlvm.WaktuMulai.DataValue = tltvm.WaktuMulai;
                tlvm.WaktuSelesai.DataValue = tltvm.WaktuSelesai;
                tlvm.IsBatal.DataValue = tltvm.IsBatal;
                TransaksiLayanans.Add(tlvm);
            }

            TransaksiProduks.Clear();
            TransaksiProdukViewModel tpvm = null;
            foreach (TransaksiProdukThumbnailViewModel tptvm in ttvm.TransaksiProduks)
            {
                tpvm = new TransaksiProdukViewModel(
                    messageBoxService,
                    uiVisualizerService,
                    referenceProvider);
                tpvm.IdTransaksiProduk.DataValue = tptvm.IdTransaksiProduk;
                tpvm.IdTransaksi.DataValue = tptvm.IdTransaksi;
                tpvm.IdJenisStok.DataValue = tptvm.IdJenisStok;
                tpvm.NamaJenisStok = tptvm.NamaJenisStok;
                tpvm.IdKaryawan.DataValue = tptvm.IdKaryawan;
                tpvm.NamaKaryawan = tptvm.NamaKaryawan;
                tpvm.JumlahProduk.DataValue = tptvm.JumlahProduk;
                tpvm.HargaProduk.DataValue = tptvm.HargaProduk;
                tpvm.PotonganHarga.DataValue = tptvm.PotonganHarga;
                tpvm.KomisiKaryawan.DataValue = tptvm.KomisiKaryawan;
                TransaksiProduks.Add(tpvm);
            }

            TransaksiPembayarans.Clear();
            TransaksiPembayaranViewModel tbvm = null;
            foreach (TransaksiPembayaranThumbnailViewModel tbtvm in ttvm.TransaksiPembayarans)
            {
                tbvm = new TransaksiPembayaranViewModel(
                    messageBoxService,
                    uiVisualizerService,
                    referenceProvider);
                tbvm.IdTransaksiPembayaran.DataValue = tbtvm.IdTransaksiPembayaran;
                tbvm.IdTransaksi.DataValue = tbtvm.IdTransaksi;
                tbvm.IdJenisPembayaran.DataValue = tbtvm.IdJenisPembayaran;
                tbvm.NominalPembayaran.DataValue = tbtvm.NominalPembayaran;
                TransaksiPembayarans.Add(tbvm);
            }
        }
        */
        private void SynchToThumbnail(KaryawanThumbnailViewModel ktvm)
        {
            ktvm.IdKaryawan = IdKaryawan.DataValue;
            ktvm.Nama = Nama.DataValue;
            ktvm.Alamat = Alamat.DataValue;
            ktvm.NoTelepon = NoTelepon.DataValue;
            ktvm.NoKTP = NoKTP.DataValue;
            ktvm.JenisKelamin = JenisKelamin.DataValue;
            ktvm.TanggalLahir = TanggalLahir.DataValue;
            ktvm.Status = Status.DataValue;
            ktvm.Agama = Agama.DataValue;
            ktvm.GolDarah = GolDarah.DataValue;
            ktvm.TanggalMasuk = TanggalMasuk.DataValue;
            ktvm.TanggalKeluar = TanggalKeluar.DataValue;
            ktvm.IdCabang = IdCabang.DataValue;

            ktvm.KaryawanLayanans = new DispatcherNotifiedObservableCollection<KaryawanLayananThumbnailViewModel>();
            KaryawanLayananThumbnailViewModel kltvm = null;
            foreach (KaryawanLayananViewModel klvm in karyawanLayanans)
            {
                kltvm = new KaryawanLayananThumbnailViewModel();
                kltvm.IdKaryawan = klvm.IdKaryawan.DataValue;
                kltvm.IdLayanan = klvm.IdLayanan.DataValue;
                kltvm.NamaLayanan = klvm.NamaLayanan;
                ktvm.KaryawanLayanans.Add(kltvm);
            }
            ktvm.KaryawanLayanansCV = CollectionViewSource.GetDefaultView(ktvm.KaryawanLayanans);

            KaryawanKehadiranThumbnailViewModel kktvm = new KaryawanKehadiranThumbnailViewModel();
            kktvm.IdKaryawanKehadiran = kehadiranTerakhir.IdKaryawanKehadiran.DataValue;
            kktvm.IdKaryawan = kehadiranTerakhir.IdKaryawanKehadiran.DataValue;
            kktvm.NamaKaryawan = kehadiranTerakhir.NamaKaryawan;
            kktvm.WaktuMasuk = kehadiranTerakhir.WaktuMasuk.DataValue;
            kktvm.WaktuKeluar = kehadiranTerakhir.WaktuKeluar.DataValue;
            ktvm.KehadiranTerakhir = kktvm;

            ktvm.JadwalKaryawans = new DispatcherNotifiedObservableCollection<TransaksiLayananThumbnailViewModel>();
            TransaksiLayananThumbnailViewModel tltvm = null;
            foreach (TransaksiLayananViewModel tlvm in jadwalKaryawans)
            {
                tltvm = new TransaksiLayananThumbnailViewModel();
                tltvm.IdTransaksiLayanan = tlvm.IdTransaksiLayanan.DataValue;
                tltvm.IdTransaksi = tlvm.IdTransaksi.DataValue;
                tltvm.IdLayanan = tlvm.IdLayanan.DataValue;
                tltvm.NamaLayanan = tlvm.NamaLayanan;
                tltvm.HargaLayanan = tlvm.HargaLayanan;
                tltvm.IdKaryawan = tlvm.IdKaryawan.DataValue;
                tltvm.NamaKaryawan = tlvm.NamaKaryawan;
                tltvm.KomisiKaryawan = tlvm.KomisiKaryawan;
                tltvm.NamaPromo = tlvm.NamaPromo.DataValue;
                tltvm.PotonganPromo = tlvm.PotonganPromo.DataValue;
                tltvm.NilaiKepuasan = tlvm.NilaiKepuasan.DataValue;
                tltvm.NamaFreeGift = tlvm.NamaFreeGift.DataValue;
                tltvm.IdJenisStok = tlvm.IdJenisStok.DataValue;
                tltvm.NamaJenisStok = tlvm.NamaJenisStok;
                tltvm.JumlahFreeGift = tlvm.JumlahFreeGift.DataValue;
                tltvm.WaktuBuat = tlvm.WaktuBuat.DataValue;
                tltvm.WaktuTunggu = tlvm.WaktuTunggu.DataValue;
                tltvm.WaktuMulai = tlvm.WaktuMulai.DataValue;
                tltvm.WaktuSelesai = tlvm.WaktuSelesai.DataValue;
                tltvm.IsBatal = tlvm.IsBatal.DataValue;
                ktvm.JadwalKaryawans.Add(tltvm);
            }
            ktvm.JadwalKaryawansCV = CollectionViewSource.GetDefaultView(ktvm.JadwalKaryawans);
        }

        #endregion
        #endregion

        #region Overrides
        static PropertyChangedEventArgs isValidChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.IsValid);
        public override bool IsValid
        {
            get
            {
                //return base.IsValid and use DataWrapperHelper, if you are
                //using DataWrappers
                return base.IsValid &&
                    DataWrapperHelper.AllValid(cachedListOfDataWrappers) &&
                    IsCollectionsValid &&
                    kehadiranTerakhir.IsValid;
            }

        }

        static PropertyChangedEventArgs isDirtyChangeArgs =
            ObservableHelper.CreateArgs<KaryawanViewModel>(x => x.IsDirty);
        public bool IsDirty 
        {
            get
            {
                return DataWrapperHelper2.SomeDirty(cachedListOfDataWrappers) ||
                    isCollectionsChanged ||
                    IsCollectionsDirty ||
                    kehadiranTerakhir.IsDirty;
            }
        }

        public override string ToString()
        {
            return String.Format("KaryawanViewModel {0}", this.idKaryawan);
        }
        #endregion

        #region EditableValidatingViewModelBase overrides
        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the BeginEdit state
        /// </summary>
        protected override void OnBeginEdit()
        {
            base.OnBeginEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call BeginEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
            foreach (var item in karyawanLayanans)
            {
                item.BeginEdit();
            }
            foreach (var item in jadwalKaryawans)
            {
                item.BeginEdit();
            }
            kehadiranTerakhir.BeginEdit();
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the EndEdit state
        /// </summary>
        protected override void OnEndEdit()
        {
            base.OnEndEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
            foreach (var item in karyawanLayanans)
            {
                item.EndEdit();
            }
            foreach (var item in jadwalKaryawans)
            {
                item.EndEdit();
            }
            kehadiranTerakhir.EndEdit();
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the CancelEdit state
        /// </summary>
        protected override void OnCancelEdit()
        {
            base.OnCancelEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
            foreach (var item in karyawanLayanans)
            {
                item.CancelEdit();
            }
            foreach (var item in jadwalKaryawans)
            {
                item.CancelEdit();
            }
            kehadiranTerakhir.CancelEdit();
        }
        #endregion
    }
}
